package callBack.impl;

import app.FileMeta;
import callBack.FileScannerCallBaack;
import util.DBUtil;
import util.PinyinUtil;

import java.io.File;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class FileSave2DB implements FileScannerCallBaack {
    @Override
    public void callback(File dir) {
        //列举出当前dir路径下的所有文件对象
        File[] files = dir.listFiles();
        //边界条件
        if(files != null && files.length != 0) {
            //1.将dir下所有文件信息保存到内存中--视图1
            List<FileMeta> locals = new ArrayList<>();
            for(File file : files) {
                FileMeta meta = new FileMeta();
                if(dir.isDirectory()) {
                    setCommonFiled(file.getName(), file.getParent(),true, file.lastModified(),meta);
                }else {
                    //是个文件有大小
                    setCommonFiled(file.getName(), file.getParent(), false, file.lastModified(), meta);
                    meta.setSize(file.length());
                }
                locals.add(meta);
            }
            //2.从数据库中查询出当前路径下的所有文件信息--视图2
            List<FileMeta> dbFiles = query(dir);
            //3.对比两个视图
            //本地有，数据库没有，插入
            for(FileMeta meta : locals) {
                if(!dbFiles.contains(meta)) {
                    save(meta);
                }
            }
            //数据库有，本地没有，删除
            for(FileMeta meta : dbFiles) {
                if(!locals.contains(meta)) {
                    delete(meta);
                }
            }
        }
        //若files == null || files.length == 0
        //该文件夹下没有文件或者不是文件夹
    }

    /**
     * 删除数据库有的，缓存中没有的数据
     * @param meta
     */
    private void delete(FileMeta meta) {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "delete from file_meta where" +
                    " (name = ? and path = ?)";
            if(meta.getIsDirectory()) {
                //若是文件夹，还需删除里面的文件夹和文件
                sql += "or path = ?"; //删除第一级目录
                sql += "or path like ?"; //删除的是多级目录
            }
            ps = connection.prepareStatement(sql);
            ps.setString(1, meta.getName());
            ps.setString(2, meta.getPath());
            if(meta.getIsDirectory()) {
                ps.setString(3, meta.getPath() + File.separator +meta.getName());
                ps.setString(4, meta.getPath() + File.separator +meta.getName() + File.separator +"%");
            }
//            System.out.println("执行删除操作，SQL为：" +ps);
            int rows = ps.executeUpdate();
//            if(meta.getIsDirectory()) {
//                System.out.println("删除文件夹" +meta.getName() +"成功，共删除" +rows +"个文件");
//            }else {
//                System.out.println("删除文件" +meta.getName() +"成功");
//            }
        } catch (SQLException e) {
            System.err.println("文件删除出错，请检查SQL语句");
            e.printStackTrace();
        }finally {
            DBUtil.close(ps);
        }
    }

    /**
     * 将指定的文件信息保存到数据库中
     * @param meta
     */
    private void save(FileMeta meta) {
        Connection connection = null;
        PreparedStatement ps = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "insert into file_meta values(?,?,?,?,?,?,?)";
            ps = connection.prepareStatement(sql);
            String fileName = meta.getName();
            ps.setString(1,fileName);
            ps.setString(2,meta.getPath());
            ps.setBoolean(3,meta.getIsDirectory());
            if(!meta.getIsDirectory()) {
                ps.setLong(4,meta.getSize());
            }
            ps.setTimestamp(5,new Timestamp(meta.getLastModified().getTime()));
            //若有中文则存入拼音
            if(PinyinUtil.containsChinese(fileName)) {
                String[] pinyins = PinyinUtil.getPinyinByFileName(fileName);
                ps.setString(6,pinyins[0]);
                ps.setString(7,pinyins[1]);
            }
//            System.out.println("执行文件操作，SQL为：" +ps);
            int rows = ps.executeUpdate();
//            System.out.println("成功保存" +rows +"行文件信息");
        } catch (SQLException e) {
            System.err.println("保存文件信息出错，请检查SQL语句");
            e.printStackTrace();
        }finally {
            DBUtil.close(ps);
        }
    }

    private List<FileMeta> query(File dir) {
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<FileMeta> dbFiles = new ArrayList<>();
        try {
            connection = DBUtil.getConnection();
            String sql = "select name,path,is_directory,size,last_modified from file_meta" +
                    " where path = ?";
            ps = connection.prepareStatement(sql);
            ps.setString(1,dir.getPath());
            rs = ps.executeQuery();
//            System.out.println("查询的指定路径的SQL为：" +ps);
            while (rs.next()) {
                FileMeta meta = new FileMeta();
                meta.setName(rs.getString("name"));
                meta.setPath(rs.getString("path"));
                meta.setIsDirectory(rs.getBoolean("is_directory"));
                meta.setLastModified(new Date(rs.getTimestamp("last_modified").getTime()));
                //若是文件设置size
                if(!meta.getIsDirectory()) {
                    meta.setSize(rs.getLong("size"));
                }
                dbFiles.add(meta);
            }
        } catch (SQLException e) {
            System.err.println("查询数据库指定路径下的文件出错，请检查SQL语句");
            e.printStackTrace();
        }finally {
            DBUtil.close(ps,rs);
        }
        return dbFiles;
    }
    private void setCommonFiled(String name,String path,boolean isDirectory,Long lastModified,FileMeta meta) {
        meta.setName(name);
        meta.setPath(path);
        meta.setDirectory(isDirectory);
        meta.setLastModified(new Date((lastModified)));
    }
}
